const fs = require('fs');
const path = require('path');
const sharp = require('sharp');

// 图片目录路径
const IMAGE_DIRS = [
  'miniprogram/images/news',
  'miniprogram/images/meals',
  'miniprogram/images/recipes',
  'miniprogram/images/discovers'
];

// 图片格式
const IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.avif'];

// 目标大小（KB）
const TARGET_SIZE = 190; // 略小于200KB的限制

// 压缩质量，可以根据需要调整
const INITIAL_QUALITY = 90;

// 创建输出目录
const OUTPUT_DIR = 'compressed_images';
if (!fs.existsSync(OUTPUT_DIR)) {
  fs.mkdirSync(OUTPUT_DIR);
}

/**
 * 获取文件大小（KB）
 */
function getFileSizeInKB(filePath) {
  const stats = fs.statSync(filePath);
  return stats.size / 1024;
}

/**
 * 递归获取目录下所有图片
 */
function getAllImages(directory) {
  const results = [];
  
  if (!fs.existsSync(directory)) {
    console.log(`目录不存在: ${directory}`);
    return results;
  }

  const files = fs.readdirSync(directory);
  
  for (const file of files) {
    const fullPath = path.join(directory, file);
    const stat = fs.statSync(fullPath);
    
    if (stat.isDirectory()) {
      // 递归处理子目录
      results.push(...getAllImages(fullPath));
    } else {
      // 检查是否是支持的图片格式
      const ext = path.extname(file).toLowerCase();
      if (IMAGE_EXTENSIONS.includes(ext)) {
        results.push(fullPath);
      }
    }
  }
  
  return results;
}

/**
 * 压缩图片
 */
async function compressImage(imagePath) {
  try {
    const fileName = path.basename(imagePath);
    const outputPath = path.join(OUTPUT_DIR, fileName);
    const originalSize = getFileSizeInKB(imagePath);
    
    // 如果图片已经小于目标大小，只需复制
    if (originalSize <= TARGET_SIZE) {
      fs.copyFileSync(imagePath, outputPath);
      console.log(`图片已复制 (${originalSize.toFixed(2)}KB): ${imagePath}`);
      return {
        path: imagePath,
        originalSize,
        newSize: originalSize,
        status: 'copied'
      };
    }
    
    // 获取图片格式
    const ext = path.extname(imagePath).toLowerCase();
    
    // 根据不同格式采用不同策略压缩
    let quality = INITIAL_QUALITY;
    let image = sharp(imagePath);
    
    // 尝试不同质量设置直到达到目标大小
    while (quality > 10) {
      let buffer;
      
      if (ext === '.png') {
        buffer = await image.png({ quality }).toBuffer();
      } else if (ext === '.avif') {
        buffer = await image.avif({ quality }).toBuffer();
      } else {
        // jpg, jpeg
        buffer = await image.jpeg({ quality }).toBuffer();
      }
      
      // 检查压缩后大小
      const compressedSize = buffer.length / 1024;
      
      if (compressedSize <= TARGET_SIZE) {
        // 写入压缩后的图片
        fs.writeFileSync(outputPath, buffer);
        console.log(`压缩成功 (${originalSize.toFixed(2)}KB -> ${compressedSize.toFixed(2)}KB, 质量: ${quality}%): ${imagePath}`);
        return {
          path: imagePath,
          originalSize,
          newSize: compressedSize,
          status: 'compressed'
        };
      }
      
      // 如果还是太大，降低质量再试
      quality -= 10;
    }
    
    // 如果降低质量仍然不能达到目标，尝试调整尺寸
    const metadata = await image.metadata();
    const newWidth = Math.floor(metadata.width * 0.8); // 缩小到80%
    
    const resizedBuffer = await image
      .resize(newWidth)
      .jpeg({ quality: 80 })
      .toBuffer();
    
    const resizedSize = resizedBuffer.length / 1024;
    
    fs.writeFileSync(outputPath, resizedBuffer);
    console.log(`调整尺寸后压缩成功 (${originalSize.toFixed(2)}KB -> ${resizedSize.toFixed(2)}KB): ${imagePath}`);
    
    return {
      path: imagePath,
      originalSize,
      newSize: resizedSize,
      status: 'resized'
    };
    
  } catch (error) {
    console.error(`压缩失败: ${imagePath}`, error);
    return {
      path: imagePath,
      error: error.message,
      status: 'error'
    };
  }
}

/**
 * 主函数
 */
async function main() {
  console.log('开始搜索图片...');
  
  let allImages = [];
  for (const dir of IMAGE_DIRS) {
    if (fs.existsSync(dir)) {
      const images = getAllImages(dir);
      allImages = [...allImages, ...images];
      console.log(`在 ${dir} 中找到 ${images.length} 张图片`);
    } else {
      console.log(`目录不存在: ${dir}`);
    }
  }
  
  console.log(`共找到 ${allImages.length} 张图片`);
  
  // 按大小排序，从大到小
  const sortedImages = allImages.map(img => ({
    path: img,
    size: getFileSizeInKB(img)
  })).sort((a, b) => b.size - a.size);
  
  console.log('\n大于200KB的图片:');
  const largeImages = sortedImages.filter(img => img.size > 200);
  largeImages.forEach(img => {
    console.log(`${img.path} (${img.size.toFixed(2)}KB)`);
  });
  
  console.log('\n开始压缩图片...');
  const results = [];
  
  for (const img of sortedImages) {
    const result = await compressImage(img.path);
    results.push(result);
  }
  
  // 输出汇总报告
  console.log('\n压缩完成！汇总报告:');
  console.log(`- 总图片数: ${results.length}`);
  console.log(`- 已压缩: ${results.filter(r => r.status === 'compressed').length}`);
  console.log(`- 已调整尺寸: ${results.filter(r => r.status === 'resized').length}`);
  console.log(`- 无需处理: ${results.filter(r => r.status === 'copied').length}`);
  console.log(`- 失败: ${results.filter(r => r.status === 'error').length}`);
  
  const originalTotalSize = results.reduce((sum, r) => sum + (r.originalSize || 0), 0);
  const newTotalSize = results.reduce((sum, r) => sum + (r.newSize || 0), 0);
  
  console.log(`\n总大小: ${originalTotalSize.toFixed(2)}KB -> ${newTotalSize.toFixed(2)}KB`);
  console.log(`节省了: ${(originalTotalSize - newTotalSize).toFixed(2)}KB (${((1 - newTotalSize/originalTotalSize) * 100).toFixed(2)}%)`);
  console.log(`\n压缩后的图片保存在 "${OUTPUT_DIR}" 目录中`);
}

main().catch(console.error); 